﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.ServiceModel;
using System.Linq;
using MSH.Common.Classes;
using MSH.Common.DAO;
using MSH.Common.DAO.Results;
using MSH.Common.Business;
using MSH.Common.Helpers;
using MSH.Common.WP7;
using NHibernate;
using NHibernate.Linq;
using System.Threading.Tasks;
using MSH.Server.Helpers;
using MSH.Server.Classes;

namespace MSH.Server.Webservice
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    [NHibernateWcfContext]
    public class MSHService : IMSHService
    {
        private static int userSessionExpireDays;

        static MSHService()
        {
            /* Laad configuratie */
            userSessionExpireDays = int.Parse(System.Configuration.ConfigurationManager.AppSettings["userSessionExpireDays"].ToString());
        }

        public MSHService()
        {

        }

        /// <summary>
        /// Probeert in te loggen met de parameters.
        /// </summary>
        /// <param name="username">De username</param>
        /// <param name="password">Het wachtwoord</param>
        /// <param name="mobilePhoneType">Het type telefoon</param>
        /// <returns>LoginResult met daarin het een loginEnum, een token(bij succesvol inloggen) en het base result.</returns>
        LoginResult IMSHService.Login(String username, String password, String mobilePhoneType)
        {
            LogHelper.LogMessage("IMSHService.Login()");

            if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password) || String.IsNullOrEmpty(mobilePhoneType))
                return null;

            LoginResult result = new LoginResult();

            try
            {
                if (UserHelper.ValidateCredentials(username, password))
                {
                    result.Result = Common.Classes.LoginResultEnum.Success;
                    result.Token = CommonHelper.StringToBase64(String.Format("{0}{1}{2}", username, Guid.NewGuid().ToString(), mobilePhoneType));

                    MobilePhoneTypeEnum mobilePhoneTypeEnum = (MobilePhoneTypeEnum)Enum.Parse(typeof(MobilePhoneTypeEnum), mobilePhoneType);
                    DeleteExistingUserSession(username);
                    UserSession us = new UserSession() { Username = username, Token = result.Token, MobilePhoneType = mobilePhoneTypeEnum, ExpirationTimestamp = DateTime.UtcNow.AddDays(userSessionExpireDays) };
                    
                    ISession session = NHibernateHelper.GetCurrentSession();
                    session.Save(us);
                    using (ITransaction trans = session.BeginTransaction())
                    {
                        trans.Commit();
                    }
                }
                else if (UserHelper.ValidateCredentialsNotActivated(username, password))
                {
                    result.Result = Common.Classes.LoginResultEnum.NotActivated;
                }
                else if (UserHelper.ValidateCredentialsNotActivatedAndExpired(username, password))
                    result.Result = Common.Classes.LoginResultEnum.NotActivatedAndExpired;
                else
                    result.Result = Common.Classes.LoginResultEnum.Failure;

                return result;

            }
            catch (Exception e)
            {
                LogHelper.LogMessage("IMSHService.Login(): " + e);

                result = new LoginResult();
                result.Result = LoginResultEnum.Failure;
                return result;
            }

        }

        /// <summary>
        /// Registreren van een nieuwe gebruiker voor MySocialHub.
        /// </summary>
        /// <param name="username">De username</param>
        /// <param name="password">Het wachtwoord</param>
        /// <param name="mobilePhoneNumber">Het mobiele telefoonnummer</param>
        /// <returns>RegisterResultEnum met daarin Succes of Failure.</returns>
        RegisterResultEnum IMSHService.Register(String username, String password, String mobilePhoneNumber)
        {
            if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password) || String.IsNullOrEmpty(mobilePhoneNumber))
                return RegisterResultEnum.Failure;

            LogHelper.LogMessage("IMSHService.Register()");

            if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password) || UserHelper.Exists(username))
                return RegisterResultEnum.Failure;

            return UserHelper.RegisterNewUser(username, password, mobilePhoneNumber) ? RegisterResultEnum.Success : RegisterResultEnum.Failure;
        }

        /// <summary>
        /// Aanvraag voor het opnieuw sturen van de activatiecode via sms.
        /// </summary>
        /// <param name="username">De username</param>
        /// <param name="password">Het wachtwoord</param>
        /// <param name="mobilePhoneNumber">Het mobiele telefoonnummer</param>
        /// <returns>ResendActivationResultEnum met als resultaat: Succes, RetriesExceeded, AlreadyActivated of Failure.</returns>
        ResendActivationResultEnum IMSHService.ResendActivationCode(String username, String password, String mobilePhoneNumber)
        {
            if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password) || String.IsNullOrEmpty(mobilePhoneNumber))
                return ResendActivationResultEnum.Failure;

            LogHelper.LogMessage("IMSHService.ResendActivationCode()");

            if (UserHelper.ValidateCredentialsNotActivated(username, password) || UserHelper.ValidateCredentialsNotActivatedAndExpired(username, password))
                return UserHelper.ResendActivationCode(username, mobilePhoneNumber);
            else if (UserHelper.ValidateCredentials(username, password))
                return ResendActivationResultEnum.AlreadyActivated;
            else
                return ResendActivationResultEnum.Success;
        }

        /// <summary>
        /// Het activeren van een account met de activatiecode uit de ontvangen sms.
        /// </summary>
        /// <param name="username">De username</param>
        /// <param name="password">Het wachtwoord</param>
        /// <param name="activationCode">De activatiecode, ontvangen via sms</param>
        /// <returns>ActivationResultEnum met als resultaat: Succes, Failure of AlreadyActivated</returns>
        ActivationResultEnum IMSHService.Activate(String username, String password, String activationCode)
        {
            if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password) || String.IsNullOrEmpty(activationCode))
                return ActivationResultEnum.Invalid;

            LogHelper.LogMessage("IMSHService.Activate()");

            if (UserHelper.ValidateCredentialsNotActivated(username, password))
            {
                if (UserHelper.ActivateUser(username, activationCode))
                    return ActivationResultEnum.Success;
                else
                    return ActivationResultEnum.Invalid;
            }
            else if (UserHelper.ValidateCredentials(username, password))
                return ActivationResultEnum.AlreadyActivated;
            else
                return ActivationResultEnum.Invalid;
        }

        /// <summary>
        /// Het updaten van de locatiegegevens van een ingelogde gebruiker.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <param name="latitude">Latitude</param>
        /// <param name="longitude">Longitude</param>
        /// <returns>UpdateLocationResult met daarin gegevens over de nieuwe locatie(Land, plaats, straat)</returns>
        UpdateLocationResult IMSHService.UpdateLocation(String token, String latitude, String longitude)
        {
            LogHelper.LogMessage("IMSHService.UpdateLocation()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            if (String.IsNullOrEmpty(latitude) || String.IsNullOrEmpty(longitude))
                return null;


            UpdateLocationResult result = new UpdateLocationResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    NumberFormatInfo numberFormatter = CultureInfo.GetCultureInfo("nl-NL").NumberFormat;
                    double lo = Convert.ToDouble(longitude, numberFormatter);
                    double la = Convert.ToDouble(latitude, numberFormatter);
                    UserLocation userLocation = UserHelper.UpdateLocation(GetUsernameFromToken(token), lo, la);
                    if (userLocation != null)
                    {
                        result.Location = new UserLocationData();
                        result.Location.AddressLine = userLocation.AddressLine;
                        result.Location.AdminDistrict = userLocation.AdminDistrict;
                        result.Location.CountryRegion = userLocation.CountryRegion;
                        result.Location.Latitude = userLocation.Latitude;
                        result.Location.Longitude = userLocation.Longitude;
                        result.Location.Locality = userLocation.Locality;
                        result.Location.PostalCode = userLocation.PostalCode;
                        result.Location.LocationUpdatedTime = userLocation.Timestamp;
                    }
                    SessionHelper.UpdateSessionLastLocationUpdate(token, DateTime.UtcNow);
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.UpdateLocation(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.UpdateLocation(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Abonneert een gebruiker op Windows Phone 7 notificaties.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <param name="uri">Windows Phone 7 push URI</param>
        WP7RegisterPushNotificationResult IMSHService.WP7RegisterPushNotification(string token, string uri)
        {
            if (String.IsNullOrEmpty(uri))
                return null;

            WP7RegisterPushNotificationResult result = new WP7RegisterPushNotificationResult();

            if (SessionHelper.IsTokenValid(token))
            {

                UserSession us = SessionHelper.GetSessionByToken(token);
                ISession session = NHibernateHelper.GetCurrentSession();

                if (us != null && us.MobilePhoneType == MobilePhoneTypeEnum.WindowsPhone7)
                {
                    us.WP7PushNotifactionURL = uri;
                    session.SaveOrUpdate(us);
                }

                using (ITransaction transaction = session.BeginTransaction())
                {
                    transaction.Commit();
                }

                return result;
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.WP7RegisterPushNotification(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Vraag een Windows Phone 7 Tile notification aan.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        WP7RequestTileNotificationResult IMSHService.WP7RequestTileNotification(string token)
        {

            WP7RequestTileNotificationResult result = new WP7RequestTileNotificationResult();

            if (SessionHelper.IsTokenValid(token))
            {

                UserSession us = SessionHelper.GetSessionByToken(token);

                if (us != null && us.MobilePhoneType == MobilePhoneTypeEnum.WindowsPhone7)
                {
                    NotificationManager.Current.Notify(us.WP7PushNotifactionURL, NotificationFactory.PrepareTile(UserHelper.GetChatMessageCount(us.Username)));
                }


                return result;
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.WP7RequestTileNotificationResult(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Opvragen van het profiel van een vriend.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <param name="username">Gebruikersnaam van een vriend.</param>
        /// <returns>GetUserProfileResult met daarin het userprofile van de vriend.</returns>
        GetUserProfileResult IMSHService.GetUserProfile(String token, String username)
        {
            LogHelper.LogMessage("IMSHService.GetUserProfile()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            if (String.IsNullOrEmpty(username))
                return null;

            GetUserProfileResult result = new GetUserProfileResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.UserProfile = UserHelper.GetUserProfile(username, GetUsernameFromToken(token));
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.GetUserProfile(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetUserProfile(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }

        }

        /// <summary>
        /// Opvragen van de vriendenlijst van de ingelogde gebruiker.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <returns>GetFriendListResult, met daarin een lijst met de vrienden van de ingelogde gebruiker.</returns>
        GetFriendListResult IMSHService.GetFriendList(String token)
        {
            LogHelper.LogMessage("IMSHService.GetFriendList()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            GetFriendListResult result = new GetFriendListResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.Friends = UserHelper.GetFriendList(GetUsernameFromToken(token));
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.GetFriendList(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetFriendList(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Opsturen van een nieuw chat bericht naar een gebruiker.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <param name="toUsername">Gebruiker voor wie het bericht bestemd is.</param>
        /// <param name="message">Bericht dat verstuurd wordt.</param>
        NewChatMessageResult IMSHService.NewChatMessage(String token, String toUsername, String message)
        {
            //TODO: controleer of ze wel werkelijk bevriend zijn, of dat het een vreemde betreft die in de buurt is
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            if (String.IsNullOrEmpty(toUsername) || String.IsNullOrEmpty(message) || message.Length > 500)
                return null;

            LogHelper.LogMessage("IMSHService.NewChatMessage()");
            NewChatMessageResult result = new NewChatMessageResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    UserSession usFrom = SessionHelper.GetSessionByToken(token);
                    UserSession usTo = SessionHelper.GetSessionByUsername(toUsername);

                    bool inDeBuurtGeweest = SessionHelper.WasPersonNearby(token, toUsername);
                    if (UserHelper.AreFriends(usFrom.Username, toUsername, true) || inDeBuurtGeweest)
                    {
                        UserHelper.NewChatMessage(usFrom.Username, toUsername, message);

                        if (!String.IsNullOrEmpty(usTo.WP7PushNotifactionURL))
                        {
                            //WP7 notifications 
                            NotificationManager.Current.Notify(usTo.WP7PushNotifactionURL, NotificationFactory.PrepareTile(UserHelper.GetChatMessageCount(toUsername)));
                            NotificationManager.Current.Notify(usTo.WP7PushNotifactionURL, NotificationFactory.PrepareToastChatMessage(usFrom.Username, message));
                            NotificationManager.Current.Notify(usTo.WP7PushNotifactionURL, NotificationFactory.PrepareRaw("NewChatMessage"));
                        }
                    }

                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.NewChatMessage(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.NewChatMessage(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Ophalen van openstaande chat berichten.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <returns>Een lijst met nog niet ontvangen chatberichten.</returns>
        GetChatMessagesResult IMSHService.GetChatMessages(String token)
        {
            LogHelper.LogMessage("IMSHService.GetChatMessages()");

            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            GetChatMessagesResult result = new GetChatMessagesResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.ChatMessages = UserHelper.GetChatMessages(GetUsernameFromToken(token));
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.GetChatMessages(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetChatMessages(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Opvragen van alle onbekende My Social Hub gebruikers in de buurt.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <param name="range">Range voor mensen in de buurt in meters</param>
        /// <returns>Een lijst van gebruikers binnen een bepaalde straal van de ingelogde gebruiker.</returns>
        GetPeopleNearbyResult IMSHService.GetPeopleNearby(String token, String range)
        {
            LogHelper.LogMessage("MSHService.GetPeopleNearby()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            GetPeopleNearbyResult result = new GetPeopleNearbyResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.People = UserHelper.GetPeopleNearby(GetUsernameFromToken(token), range);
                    if (result.People != null)
                    {
                        UserSession currentSession = SessionHelper.GetSessionByToken(token);
                        //Werk lijst met gebruikers die in de buurt zijn geweest bij
                        if (currentSession != null)
                        {
                            foreach (MSH.Common.DAO.PersonNearby pn in result.People)
                            {
                                if (!SessionHelper.WasPersonNearby(token, pn.Username))
                                    currentSession.PersonNearby.Add(new MSH.Common.Business.PersonNearby() { Username = pn.Username });
                            }
                        }
                    }
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.GetPeopleNearby(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetPeopleNearby(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Haal de gebruikersnaam op aan de hand van het token.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <returns>De username.</returns>
        private String GetUsernameFromToken(String token)
        {
            UserSession us = SessionHelper.GetSessionByToken(token);

            if (us != null)
                return us.Username;
            else
                return null;
        }

        /// <summary>
        /// Verwijdert een bestaande UserSessions a.d.h.v. een opgegeven gebruikersnaam.
        /// </summary>
        /// <param name="username">Gebruikersnaam die hoort bij de te verwijderen UserSession.</param>
        private void DeleteExistingUserSession(String username)
        {
            SessionHelper.DeleteSessionByUsername(username);
        }

        /// <summary>
        /// Maak een nieuwe vriend relatie, waarbij het accepted veld nog false is.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <param name="username">Username van de toe te voegen vriend</param>
        /// <returns>AddFriendResult met enum</returns>
        AddFriendResult IMSHService.AddFriend(String token, String username)
        {
            LogHelper.LogMessage("MSHService.AddFriend()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            AddFriendResult result = new AddFriendResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    MSH.Common.Business.User friend = UserHelper.Get(username);
                    if (friend == null)
                    {
                        result.Result = AddFriendResultEnum.UserNotExists;
                        LogHelper.LogMessage("IMSHService.AddFriend(): Friend does not exists.");
                        return result;
                    }
                    else
                    {
                        String uname = GetUsernameFromToken(token);

                        MSH.Common.Business.User user = UserHelper.Get(uname);
                        if (user == null)
                        {
                            result.Exception = true;
                            return result;
                        }
                        else
                        {
                            if (UserHelper.AreFriends(user.Username, friend.Username, false))
                            {
                                result.Result = AddFriendResultEnum.FriendAlreadyRegistered;
                                LogHelper.LogMessage("IMSHService.AddFriend(): Users are already friends or invitation has been already sent.");
                                return result;
                            }
                            else
                            {
                                UserHelper.AddFriendRelation(user, friend);
                                result.Result = AddFriendResultEnum.Succes;
                                return result;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.AddFriend(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.AddFriend(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        SearchPeopleResult IMSHService.SearchPeople(string token, string username, string firstname, string surname, string age, string city, string phonenumber, int first, int skip)
        {
            LogHelper.LogMessage("MSHService.SearchPeople()");

            //Controleer of er geldige zoekparameters zijn opgegeven                   

            SearchPeopleResult result = new SearchPeopleResult();

            if (String.IsNullOrEmpty(username) && String.IsNullOrEmpty(firstname) && String.IsNullOrEmpty(surname) && String.IsNullOrEmpty(age) && String.IsNullOrEmpty(city) && String.IsNullOrEmpty(phonenumber))
                return result;

            if (SessionHelper.IsTokenValid(token))
            {
                String uname = GetUsernameFromToken(token);
                UserHelper.UpdateLastSeenTimestamp(uname);

                MSH.Common.Business.User user = UserHelper.Get(uname);

                //Haal hashset met usernames van vrienden op.
                HashSet<String> userFriends = UserHelper.GetListOfFriendUsernames(user.ID);

                if (first > 50)
                    first = 50;

                result.Results = new List<SearchResult>();

                String sql = "select first 250 {US.*} from \"USER\" US " +
                             "left join USERSETTINGS USET on (US.USERSETTINGS = USET.ID) " +
                             "left join \"USERPROFILE\" UF on UF.ID = US.USERPROFILE  " +
                             "AND ( (exists(select 1 from USERFRIEND UF where UF.PARENTUSER = US.ID AND UF.FRIEND = " + user.ID + " ) AND USET.PROFILEPRIVACY = " + (int)PrivacyEnum.Friends + ") OR (USET.PROFILEPRIVACY = " + (int)PrivacyEnum.Public + ")) " +
                             "left join USERLOCATION UL on (US.LASTUSERLOCATION = UL.ID)";
      
                String sqlWhere = "WHERE US.ID != " + user.ID;
                
                if (!String.IsNullOrEmpty(username))
                    sqlWhere += " AND UPPER(USERNAME) starting with UPPER(:username)";

                if (!String.IsNullOrEmpty(firstname))
                    sqlWhere += " AND UPPER(FIRSTNAME) starting with UPPER(:firstname)";

                if (!String.IsNullOrEmpty(surname))
                    sqlWhere += " AND UPPER(SURNAME) starting with UPPER(:surname)";

                if (!String.IsNullOrEmpty(age))
                    sqlWhere += " AND extract(year from DATEOFBIRTH) - extract(year from current_timestamp) = :age";

                if (!String.IsNullOrEmpty(city))
                    sqlWhere += " AND UPPER(CITY) starting with UPPER(:city)";

                if (!String.IsNullOrEmpty(phonenumber))
                    sqlWhere += " AND MOBILEPHONENUMBER starting with :MOBILEPHONENUMBER";

                String sqlOrderBy = "ORDER BY IIF(EXISTS(SELECT ID FROM USERFRIEND WHERE PARENTUSER = " + user.ID + " AND FRIEND = US.ID), 0, 1)";

                if (user.LastUserLocation != null)
                    sqlOrderBy += ", ACOS(SIN(:lat)*SIN(ul.LATITUDE/180) +COS(:lat)*COS(ul.LATITUDE/180)*COS((ul.LONGITUDE-:lon)/180))*6371";

                ISession session = NHibernateHelper.GetCurrentSession();
                IQuery qFriends = session.CreateSQLQuery(sql + " " + sqlWhere + " " + sqlOrderBy).AddEntity("US", typeof(MSH.Common.Business.User));                


                if (user.LastUserLocation != null)
                {
                    qFriends.SetDouble("lat", user.LastUserLocation.Latitude);
                    qFriends.SetDouble("lon", user.LastUserLocation.Longitude);
                }

                if (!String.IsNullOrEmpty(username))
                {
                    qFriends.SetString("username", username);
                }
                if (!String.IsNullOrEmpty(firstname))
                {
                    qFriends.SetString("firstname", firstname);
                }
                if (!String.IsNullOrEmpty(surname))
                {
                    qFriends.SetString("surname", surname);
                }
                if (!String.IsNullOrEmpty(age))
                {
                    qFriends.SetString("age", age);
                }
                if (!String.IsNullOrEmpty(city))
                {
                    qFriends.SetString("city", city);
                }
                if (!String.IsNullOrEmpty(phonenumber))
                {
                    qFriends.SetString("phonenumber", phonenumber);           
                }

                IList<MSH.Common.Business.User> results = qFriends.List<MSH.Common.Business.User>();

                result.ResultCount = results.Count;

                int i = -1;
                int count = 1;

                foreach (MSH.Common.Business.User u in results)
                {
                    i++;

                    if (i < skip)
                        continue;

                    if (count > first)
                        break;
                    
                    count++;

                    bool isFriend = userFriends.Contains(u.Username); 

                    SearchResult searchResult = CreateSearchResult(user, u, isFriend);
                    result.Results.Add(searchResult);
                }

                return result;
            }
            else
            {
                LogHelper.LogMessage(String.Format("MSHService.SearchPeople(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }

        }

        private static SearchResult CreateSearchResult(MSH.Common.Business.User user, MSH.Common.Business.User friend, bool isFriend)
        {
            SearchResult searchResult = new SearchResult();
            if ((friend.UserSettings.ProfilePrivacy == PrivacyEnum.Friends && isFriend) || 
                friend.UserSettings.ProfilePrivacy == PrivacyEnum.Public)
            {
                searchResult.FirstName = friend.UserProfile.FirstName;
                searchResult.SurName = friend.UserProfile.SurName;
            }
            searchResult.Username = friend.Username;
            searchResult.IsFriend = isFriend;
            searchResult.ProfilePrivacy = friend.UserSettings.ProfilePrivacy;
           
            if (friend.LastUserLocation != null
                && ((friend.UserSettings.LocationPrivacy == PrivacyEnum.Friends && isFriend) || 
                friend.UserSettings.LocationPrivacy == PrivacyEnum.Public)
                )
            {
                searchResult.Location = new UserLocationData()
                {
                    AddressLine = friend.LastUserLocation.AddressLine,
                    AdminDistrict = friend.LastUserLocation.AdminDistrict,
                    CountryRegion = friend.LastUserLocation.CountryRegion,
                    Latitude = friend.LastUserLocation.Latitude,
                    Locality = friend.LastUserLocation.Locality,
                    Longitude = friend.LastUserLocation.Longitude,
                    PostalCode = friend.LastUserLocation.PostalCode,
                    LocationUpdatedTime = friend.LastUserLocation.Timestamp
                };
                searchResult.Location.Distance = LocationHelper.CalculateDistance(friend.LastUserLocation.Latitude, user.LastUserLocation.Latitude, user.LastUserLocation.Longitude, user.LastUserLocation.Longitude);
            }
            
            return searchResult;
        }

        /// <summary>
        /// Blokkeer een vriend
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <param name="username">Username van de te blokkeren vriend</param>
        /// <returns>BlockFriendResult met enum</returns>
        BlockFriendResult IMSHService.BlockFriend(String token, String username)
        {
            LogHelper.LogMessage("MSHService.BlockFriend()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            BlockFriendResult result = new BlockFriendResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    MSH.Common.Business.User friend = UserHelper.Get(username);
                    if (friend == null)
                    {
                        result.Result = BlockFriendResultEnum.UserNotExists;
                        LogHelper.LogMessage("IMSHService.BlockFriend(): User not exists.");
                        return result;
                    }
                    else
                    {
                        String uname = GetUsernameFromToken(token);
                        if (String.IsNullOrEmpty(uname))
                        {
                            result.Result = BlockFriendResultEnum.UserNotExists;
                            LogHelper.LogMessage("IMSHService.BlockFriend(): Token does not contain a username.");
                            return result;
                        }

                        MSH.Common.Business.User user = UserHelper.Get(uname);
                        if (user == null)
                        {
                            result.Result = BlockFriendResultEnum.UserNotExists;
                            LogHelper.LogMessage("IMSHService.BlockFriend(): User with username from token does not exist.");
                            return result;
                        }
                        else
                        {
                            if (!UserHelper.AreFriends(user.Username, friend.Username, false))
                            {
                                result.Result = BlockFriendResultEnum.NotAFriend;
                                LogHelper.LogMessage("IMSHService.BlockFriend(): Users is not a friend");
                                return result;
                            }
                            else if (!UserHelper.AreFriends(user.Username, friend.Username, true))
                            {
                                //User if already blocked
                                result.Result = BlockFriendResultEnum.FriendAlreadyBlocked;
                                LogHelper.LogMessage("IMSHService.BlockFriend(): Users is already blocked");
                                return result;
                            }
                            else
                            {
                                UserHelper.BlockFriend(user, friend);
                                result.Result = BlockFriendResultEnum.Succes;
                                return result;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.BlockFriend(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.BlockFriend(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Deblokkeer een vriend
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <param name="username">Username van de te blokkeren vriend</param>
        /// <returns>UnblockFriendResult met enum</returns>
        UnblockFriendResult IMSHService.UnblockFriend(String token, String username)
        {
            LogHelper.LogMessage("MSHService.BlockFriend()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            UnblockFriendResult result = new UnblockFriendResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    MSH.Common.Business.User friend = UserHelper.Get(username);
                    if (friend == null)
                    {
                        result.Result = UnblockFriendResultEnum.UserNotExists;
                        LogHelper.LogMessage("IMSHService.UnblockFriend(): User not exists.");
                        return result;
                    }
                    else
                    {
                        String uname = GetUsernameFromToken(token);
                        if (String.IsNullOrEmpty(uname))
                        {
                            result.Result = UnblockFriendResultEnum.UserNotExists;
                            LogHelper.LogMessage("IMSHService.UnblockFriend(): Token does not contain a username.");
                            return result;
                        }

                        MSH.Common.Business.User user = UserHelper.Get(uname);
                        if (user == null)
                        {
                            result.Result = UnblockFriendResultEnum.UserNotExists;
                            LogHelper.LogMessage("IMSHService.UnblockFriend(): User with username from token does not exist.");
                            return result;
                        }
                        else
                        {
                            if (!UserHelper.AreFriends(user.Username, friend.Username, false))
                            {
                                result.Result = UnblockFriendResultEnum.NotAFriend;
                                LogHelper.LogMessage("IMSHService.UnblockFriend(): Users is not a friend");
                                return result;
                            }
                            else if (UserHelper.AreFriends(user.Username, friend.Username, true))
                            {
                                //User if already blocked
                                result.Result = UnblockFriendResultEnum.FriendNotBlocked;
                                LogHelper.LogMessage("IMSHService.UnblockFriend(): Users is not blocked");
                                return result;
                            }
                            else
                            {
                                UserHelper.UnblockFriend(user, friend);
                                result.Result = UnblockFriendResultEnum.Succes;
                                return result;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.UnblockFriend(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.UnblockFriend(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Een lijst met mensen die de ingelogde gebruiker uitgenodigd hebben als vriend opvragen
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <returns>GetFriendInvitationsResult, met daarin een lijst met binnenkomende invitaties.</returns>
        GetFriendInvitationsResult IMSHService.GetFriendInvitations(String token)
        {
            LogHelper.LogMessage("IMSHService.GetFriendInvitations()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            GetFriendInvitationsResult result = new GetFriendInvitationsResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.Friends = UserHelper.GetInvitationList(GetUsernameFromToken(token));
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.GetFriendInvitations(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetFriendInvitations(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Een verzoek tot vrienden accepteren
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <param name="username">Gebruikersnaam van de vriend</param>
        /// <returns>AcceptFriendInvitationResult, met daarin een enumeratie met het resultaat.</returns>
        AcceptFriendInvitationResult IMSHService.AcceptFriendInvitation(String token, String username)
        {
            LogHelper.LogMessage("IMSHService.AcceptFriendInvitation()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            AcceptFriendInvitationResult result = new AcceptFriendInvitationResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.Result = UserHelper.AcceptFriendInvitation(GetUsernameFromToken(token), username);
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.AcceptFriendInvitationResult(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.AcceptFriendInvitationResult(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Een verzoek tot vrienden afwijzen
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <param name="username">Gebruikersnaam van de vriend</param>
        /// <returns>DeclineFriendInvitationResult, met daarin een enumeratie met het resultaat.</returns>
        DeclineFriendInvitationResult IMSHService.DeclineFriendInvitation(String token, String username)
        {
            LogHelper.LogMessage("IMSHService.DeclineFriendInvitation()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            DeclineFriendInvitationResult result = new DeclineFriendInvitationResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.Result = UserHelper.DeclineFriendInvitation(GetUsernameFromToken(token), username);
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.DeclineFriendInvitationResult(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.DeclineFriendInvitationResult(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        /// <summary>
        /// Verwijderen van een vriend
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <param name="username">Gebruikersnaam van de vriend</param>
        /// <returns></returns>
        RemoveFriendResult IMSHService.RemoveFriend(String token, String username)
        {
            LogHelper.LogMessage("IMSHService.RemoveFriend()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            RemoveFriendResult result = new RemoveFriendResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.Result = UserHelper.RemoveFriend(GetUsernameFromToken(token), username);
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.RemoveFriend(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.RemoveFriend(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }

        }

        SetStatusResult IMSHService.SetStatus(String token, String status)
        {
            LogHelper.LogMessage("IMSHService.SetStatus()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            SetStatusResult result = new SetStatusResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    UserHelper.SetStatus(GetUsernameFromToken(token), status);
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.SetStatus(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.SetStatus(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }

        }

        GetSocialNetworkAccountsResult IMSHService.GetSocialNetworkAccounts(string token, string includeLogos)
        {
            LogHelper.LogMessage("IMSHService.GetSocialNetworkAccounts()");

            GetSocialNetworkAccountsResult result = new GetSocialNetworkAccountsResult();

            if (SessionHelper.IsTokenValid(token))
            {
                String username = GetUsernameFromToken(token);
                UserHelper.UpdateLastSeenTimestamp(username);

                MSH.Common.Business.User u = UserHelper.Get(username);

                result.Accounts = new List<SocialNetworkAccount>();

                foreach (ISocialNetworkProvider provider in SocialNetworkManager.RegisteredProviders)
                {
                    bool authenticated = false;
                    foreach (UserSocialNetworkAccount ac in u.UserSocialNetworkAccounts)
                    {
                        if (ac.AccountType == provider.GetName())
                        {
                            authenticated = true;
                            break;
                        }
                    }

                    SocialNetworkAccount acc = new SocialNetworkAccount()
                    {
                        Name = provider.GetName(),
                        AuthenticationURL = provider.GenerateAuthenticationURL(),
                        Authenticated = authenticated,
                        AuthenticationFinishedURL = provider.GetAuthenticationFinishedUrl(),
                        LogoChecksum = provider.GetLogoChecksum()
                    };

                    if (!String.IsNullOrEmpty(includeLogos) && includeLogos == "True")
                        acc.Logo = provider.GetLogo();
                    result.Accounts.Add(acc);
                }

                return result;
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetSupportedSocialNetworks(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }


        ValidateSocialNetworkAuthenticationURLResult IMSHService.ValidateSocialNetworkAuthenticationURL(string token, string provider, string url)
        {
            url = CommonHelper.Base64ToString(url);
            LogHelper.LogMessage("IMSHService.ValidateSocialNetworkAuthenticationURL()");

            ValidateSocialNetworkAuthenticationURLResult result = new ValidateSocialNetworkAuthenticationURLResult();

            if (SessionHelper.IsTokenValid(token))
            {
                String username = GetUsernameFromToken(token);
                UserHelper.UpdateLastSeenTimestamp(username);
                MSH.Common.Business.User u = UserHelper.Get(username);

                result.IsValid = false;

                ISession session = NHibernateHelper.GetCurrentSession();

                foreach (ISocialNetworkProvider snp in SocialNetworkManager.RegisteredProviders)
                {
                    if (snp.GetName() == provider)
                    {
                        String authToken = null;
                        if (snp.ParseAuthenticationURL(url, out authToken))
                        {
                            foreach (UserSocialNetworkAccount acc in u.UserSocialNetworkAccounts)
                            {
                                if (acc.AccountType == provider)
                                {
                                    u.UserSocialNetworkAccounts.Remove(acc);
                                }
                                break;
                            }

                            u.UserSocialNetworkAccounts.Add(new UserSocialNetworkAccount()
                                              {
                                                  AccountType = snp.GetName(),
                                                  Token = authToken,
                                                  User = u
                                              }

                            );

                            using (ITransaction transaction = session.BeginTransaction())
                            {
                                session.Save(u);
                                transaction.Commit();
                            }


                            result.IsValid = true;


                            if (provider == "Facebook")
                            {
                                Parallel.Invoke(() => FacebookHelper.UpdateFacebookData(username));
                                Parallel.Invoke(() => FacebookHelper.GetFacebookFriends(username));
                            }
       
                        }


                        break;
                    }
                }

                return result;
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.ValidateSocialNetworkAuthenticationURL(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        RemoveSocialNetworkAccountResult IMSHService.RemoveSocialNetworkAccount(string token, string provider)
        {
            LogHelper.LogMessage("IMSHService.RemoveSocialNetworkAccount()");

            RemoveSocialNetworkAccountResult result = new RemoveSocialNetworkAccountResult();

            if (SessionHelper.IsTokenValid(token))
            {
                String username = GetUsernameFromToken(token);
                UserHelper.UpdateLastSeenTimestamp(username);
                MSH.Common.Business.User u = UserHelper.Get(username);

                ISession session = NHibernateHelper.GetCurrentSession();

                foreach (UserSocialNetworkAccount acc in u.UserSocialNetworkAccounts)
                {
                    if (acc.AccountType == provider)
                    {
                        u.UserSocialNetworkAccounts.Remove(acc);
                        List<UserSocialNetworkProfileData> itemsToDelete = new List<UserSocialNetworkProfileData>();

                        foreach (UserSocialNetworkProfileData pd in u.UserSocialNetworkProfileData)
                        {
                            if (pd.AccountType == provider)
                                itemsToDelete.Add(pd);
                        }

                        foreach (UserSocialNetworkProfileData pd in itemsToDelete)
                            u.UserSocialNetworkProfileData.Remove(pd);

                        break;
                    }
                }


                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Save(u);
                    transaction.Commit();
                }

                return result;
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.RemoveSocialNetworkAccount(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }


        /// <summary>
        /// Het update van de instellingen
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <param name="locationPrivacy">Privacy instelling voor locatie</param>
        /// <param name="profilePrivacy">Privacy instelling voor profiel</param>
        /// <returns></returns>
        UpdateSettingsResult IMSHService.UpdateSettings(String token, String locationPrivacy, String profilePrivacy)
        {
            LogHelper.LogMessage("IMSHService.UpdateSettings()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            UpdateSettingsResult result = new UpdateSettingsResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    PrivacyEnum locationPrivacyEnum = (PrivacyEnum)Enum.Parse(typeof(PrivacyEnum), locationPrivacy);
                    PrivacyEnum profilePrivacyEnum = (PrivacyEnum)Enum.Parse(typeof(PrivacyEnum), profilePrivacy);
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    UserHelper.UpdateSettings(GetUsernameFromToken(token), locationPrivacyEnum, profilePrivacyEnum);
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.UpdateSettings(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.UpdateSettings(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        UpdateProfileResult IMSHService.UpdateProfile(String token, String phoneNumber, String firstName, String surname, String address, String zipcode, String city, String sex, String dateOfBirth, String website)
        {
            LogHelper.LogMessage("IMSHService.UpdateProfile()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            UpdateProfileResult result = new UpdateProfileResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    UserHelper.UpdateProfile(GetUsernameFromToken(token), firstName, surname, address, zipcode, city, sex, dateOfBirth, website);
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.UpdateProfile(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.UpdateProfile(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }


        /// <summary>
        /// Maak een nieuwe vriend relatie aan de hand van het telefoonnummer, waarbij het accepted veld nog false is.
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker</param>
        /// <param name="username">Telefoonnummer van de toe te voegen vriend</param>
        /// <returns>AddFriendByPhoneNumberResult met enum</returns>
        AddFriendByPhoneNumberResult IMSHService.AddFriendByPhoneNumber(String token, String phoneNumber)
        {
            LogHelper.LogMessage("MSHService.AddFriendByPhoneNumber()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            AddFriendByPhoneNumberResult result = new AddFriendByPhoneNumberResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    MSH.Common.Business.User friend = UserHelper.GetFriendByPhoneNumber(phoneNumber);
                    if (friend == null)
                    {
                        result.Result = AddFriendByPhoneNumberResultEnum.UserNotExists;
                        LogHelper.LogMessage("IMSHService.AddFriendByPhoneNumber(): Friend does not exists.");
                        return result;
                    }
                    else
                    {
                        String uname = GetUsernameFromToken(token);

                        MSH.Common.Business.User user = UserHelper.Get(uname);
                        if (user == null)
                        {
                            result.Exception = true;
                            return result;
                        }
                        else
                        {
                            if (UserHelper.AreFriends(user.Username, friend.Username, false))
                            {
                                result.Result = AddFriendByPhoneNumberResultEnum.FriendAlreadyRegistered;
                                LogHelper.LogMessage("IMSHService.AddFriendByPhoneNumber(): Users are already friends or invitation has been already sent.");
                                return result;
                            }
                            else
                            {
                                UserHelper.AddFriendRelation(user, friend);
                                result.Result = AddFriendByPhoneNumberResultEnum.Succes;
                                return result;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.AddFriendByPhoneNumber(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.AddFriendByPhoneNumber(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        AddFriendNotificationResult IMSHService.AddFriendNotification(String token, String friendUsername, String latitude, String longitude, String range)
        {
            LogHelper.LogMessage("MSHService.AddFriendNotification()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            AddFriendNotificationResult result = new AddFriendNotificationResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;

                    if (!string.IsNullOrEmpty(latitude) && !string.IsNullOrEmpty(longitude))
                    {
                        NumberFormatInfo numberFormatter = CultureInfo.GetCultureInfo("nl-NL").NumberFormat;
                        double lo = Convert.ToDouble(longitude, numberFormatter);
                        double la = Convert.ToDouble(latitude, numberFormatter);
                        double ra = Convert.ToDouble(range, numberFormatter);

                        result.Result = UserHelper.AddFriendNotification(SessionHelper.GetSessionByToken(token).Username, friendUsername, la, lo, ra);


                    }
                    else
                    {
                        LogHelper.LogMessage("MSHService.AddFriendNotification(): longitude or latitude is empty, can't add notification");
                        //result.Result = AddFriendNotificationResultEnum.EmptyLongOrLat;
                    }

                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.AddFriendNotification(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.AddFriendNotification(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        GetFriendNotificationResult IMSHService.GetFriendNotification(String token, String friendUsername)
        {
            LogHelper.LogMessage("MSHService.GetFriendNotification()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            GetFriendNotificationResult result = new GetFriendNotificationResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;

                    ISession session = NHibernateHelper.GetCurrentSession();
                    List<UserNotification> notification = session.Query<UserNotification>()
                                                          .Where(un => un.User.Username == GetUsernameFromToken(token) && un.Friend.Username == friendUsername)
                                                          .ToList<UserNotification>();

                    if (notification.Count == 1)
                    {
                        result.Notification = new MSH.Common.DAO.Notification() 
                        {  
                            FriendUsername = notification[0].Friend.Username, 
                            Latitude = notification[0].Latitude,
                            Longitude = notification[0].Longitude,
                            Range = notification[0].Range,
                        };
                    }

                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.GetFriendNotification(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetFriendNotification(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }


        /// <summary>
        /// Een lijst met suggesties voor vrienden adv social media data
        /// </summary>
        /// <param name="token">Token van de ingelogde gebruiker.</param>
        /// <returns>GetFriendSuggestionsResult, met daarin een lijst met suggesties.</returns>
        GetFriendSuggestionsResult IMSHService.GetFriendSuggestions(String token)
        {
            LogHelper.LogMessage("IMSHService.GetFriendSuggestions()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            GetFriendSuggestionsResult result = new GetFriendSuggestionsResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    result.Suggestions = UserHelper.GetFriendSuggestions(GetUsernameFromToken(token));
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.GetFriendSuggestions(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.GetFriendSuggestions(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        ChangePasswordRequestResult IMSHService.ChangePasswordRequest(String username, String newPassword, String mobilePhoneNumber)
        {
            LogHelper.LogMessage("IMSHService.ChangePassewordRequest()");

            ChangePasswordRequestResult result = new ChangePasswordRequestResult();
            try
            {
                MSH.Common.Business.User user = UserHelper.Get(username);
                if (user == null)
                    result.Result = ChangePasswordRequestResultEnum.UserNotExists;
                else
                {
                    if (!user.UserProfile.MobilePhoneNumber.Equals(mobilePhoneNumber))
                        result.Result = ChangePasswordRequestResultEnum.IncorrectMobilePhoneNumber;
                    else
                    {
                        if (user.Password.Equals(newPassword))
                        {
                            result.Result = ChangePasswordRequestResultEnum.SamePassword;
                            return result;
                        }

                        ISession session = NHibernateHelper.GetCurrentSession();
                        List<PasswordRequest> requestList = session.Query<PasswordRequest>().Where(pr => pr.User == user).ToList<PasswordRequest>();
                        //Verwijderd bestaande requests
                        int alreadyRequested = 0;
                        foreach (PasswordRequest r in requestList)
                        {
                            if (r.Requests > alreadyRequested)
                                alreadyRequested = r.Requests;
                            if (r.Requests == 3)
                            {
                            }
                            else
                                session.Delete(r);
                        }

                        if (alreadyRequested >= 3)
                        {
                            result.Result = ChangePasswordRequestResultEnum.ToManyRequests;
                        }
                        else
                        {
                            alreadyRequested++;
                            //voeg nieuw request toe en stuur activatiecode
                            int activationCode = new Random().Next(10000000, 99999999);

                            PasswordRequest req = new PasswordRequest() { User = user, Password = newPassword, Code = activationCode.ToString(), Requests = alreadyRequested };

                            session.Save(req);

                            SMSHelper.SendSMS(user.UserProfile.MobilePhoneNumber, string.Format("Enter this code to change youre password. Code: {0}", activationCode));

                            result.Result = ChangePasswordRequestResultEnum.Succes;
                        }
                        using (ITransaction trans = session.BeginTransaction())
                        {
                            trans.Commit();
                        }
                    }   
                }

                return result;
            }
            catch (Exception e)
            {
                LogHelper.LogMessage("IMSHService.ChangePassewordRequest(): " + e);
                result.Exception = true;
                return result;
            }
        }

        ActivatePasswordRequestResult IMSHService.ActivatePasswordRequest(String username, String activationCode)
        {
            LogHelper.LogMessage("IMSHService.ActivatePasswordRequest()");

            ActivatePasswordRequestResult result = new ActivatePasswordRequestResult();
            try
            {
                MSH.Common.Business.User user = UserHelper.Get(username);
                if (user == null)
                    result.Result = ActivatePasswordRequestResultEnum.UserNotExists;
                else
                {
                    ISession session = NHibernateHelper.GetCurrentSession();
                    List<PasswordRequest> requestList = session.Query<PasswordRequest>().Where(pr => pr.User == user).ToList<PasswordRequest>();
                    if (requestList.Count == 0)
                        result.Result = ActivatePasswordRequestResultEnum.NoOpenPasswordRequest;
                    else
                    {
                        foreach (PasswordRequest r in requestList)
                        {
                            if (r.Code == activationCode)
                            {
                                //Password bij het account wijzigen en verwijderen van het request.
                                user.Password = r.Password;

                                session.Save(user);
                                session.Delete(r);
                                result.Result = ActivatePasswordRequestResultEnum.Succes;
                            }
                            else
                            {
                                result.Result = ActivatePasswordRequestResultEnum.CodeNotValid;
                            }
                        }
                    }

                    using (ITransaction trans = session.BeginTransaction())
                    {
                        trans.Commit();
                    }

                }

                return result;
            }
            catch (Exception e)
            {
                LogHelper.LogMessage("IMSHService.ActivatePasswordRequest(): " + e);
                result.Exception = true;
                return result;
            }
        }

        ChangeMobilePhoneNumberRequestResult IMSHService.ChangeMobilePhoneNumberRequest(String token, String newMobilePhoneNumber, String password)
        {
            LogHelper.LogMessage("IMSHService.ChangeMobilePhoneNumberRequest()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            
            ChangeMobilePhoneNumberRequestResult result = new ChangeMobilePhoneNumberRequestResult();
            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    MSH.Common.Business.User user = UserHelper.Get(GetUsernameFromToken(token));
                    if (user == null)
                        result.Result = ChangeMobilePhoneNumberRequestResultEnum.UserNotExists;
                    else
                    {
                        if (user.Password != password)
                        {
                            result.Result = ChangeMobilePhoneNumberRequestResultEnum.IncorrectPassword;
                            return result;
                        }
                        if (user.UserProfile.MobilePhoneNumber.Equals(newMobilePhoneNumber))
                        {
                            result.Result = ChangeMobilePhoneNumberRequestResultEnum.SameNumber;
                            return result;
                        }

                        ISession session = NHibernateHelper.GetCurrentSession();
                        List<MobileNumberRequest> requestList = session.Query<MobileNumberRequest>().Where(mr => mr.User == user).ToList<MobileNumberRequest>();
                        //Verwijderd bestaande requests
                        int alreadyRequested = 0;
                        foreach (MobileNumberRequest r in requestList)
                        {
                            if (r.Requests > alreadyRequested)
                                alreadyRequested = r.Requests;
                            if (r.Requests == 3)
                            {
                            }
                            else
                                session.Delete(r);
                        }

                        if (alreadyRequested >= 3)
                        {
                            result.Result = ChangeMobilePhoneNumberRequestResultEnum.ToManyRequests;
                        }
                        else
                        {
                            alreadyRequested++;
                            //voeg nieuw request toe en stuur activatiecode
                            int activationCode = new Random().Next(10000000, 99999999);

                            MobileNumberRequest req = new MobileNumberRequest() { User = user, MobilePhoneNumber = newMobilePhoneNumber, Code = activationCode.ToString(), Requests = alreadyRequested };

                            session.Save(req);

                            SMSHelper.SendSMS(newMobilePhoneNumber, string.Format("Enter this code to change youre mobile phone number. Code: {0}", activationCode));

                            result.Result = ChangeMobilePhoneNumberRequestResultEnum.Succes;
                        }
                        using (ITransaction trans = session.BeginTransaction())
                        {
                            trans.Commit();
                        }
                    }
                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.ChangeMobilePhoneNumberRequest(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.ChangeMobilePhoneNumberRequest(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        ActivateMobilePhoneNumberRequestResult IMSHService.ActivateMobilePhoneNumberRequest(String token, String activationCode)
        {
            LogHelper.LogMessage("IMSHService.ActivateMobilePhoneNumberRequest()");
            UserHelper.UpdateLastSeenTimestamp(GetUsernameFromToken(token));

            ActivateMobilePhoneNumberRequestResult result = new ActivateMobilePhoneNumberRequestResult();

            if (SessionHelper.IsTokenValid(token))
            {
                try
                {
                    result.TokenValidationResult = TokenValidationResultEnum.Valid;
                    MSH.Common.Business.User user = UserHelper.Get(GetUsernameFromToken(token));
                    if (user == null)
                        result.Result = ActivateMobilePhoneNumberRequestResultEnum.UserNotExists;
                    else
                    {
                        ISession session = NHibernateHelper.GetCurrentSession();
                        List<MobileNumberRequest> requestList = session.Query<MobileNumberRequest>().Where(mr => mr.User == user).ToList<MobileNumberRequest>();
                        if (requestList.Count == 0)
                            result.Result = ActivateMobilePhoneNumberRequestResultEnum.NoOpenMobileNumberRequest;
                        else
                        {
                            foreach (MobileNumberRequest r in requestList)
                            {
                                if (r.Code == activationCode)
                                {
                                    //Password bij het account wijzigen en verwijderen van het request.
                                    user.UserProfile.MobilePhoneNumber = r.MobilePhoneNumber;

                                    session.Save(user);
                                    session.Delete(r);
                                    result.Result = ActivateMobilePhoneNumberRequestResultEnum.Succes;
                                }
                                else
                                {
                                    result.Result = ActivateMobilePhoneNumberRequestResultEnum.CodeNotValid;
                                }
                            }
                        }

                        using (ITransaction trans = session.BeginTransaction())
                        {
                            trans.Commit();
                        }

                    }

                    return result;
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("IMSHService.ActivateMobilePhoneNumberRequest(): " + e);
                    result.Exception = true;
                    return result;
                }
            }
            else
            {
                LogHelper.LogMessage(String.Format("IMSHService.ActivateMobilePhoneNumberRequest(): Invalid token '{0}'", token));
                result.TokenValidationResult = TokenValidationResultEnum.Invalid;
                return result;
            }
        }

        Boolean IMSHService.IsOnline()
        {
            return true;
        }
    }
}
